package top.haijunit.work.core.annotate;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;

import java.io.IOException;
import java.util.Objects;

/**
 * 【说明类功能】
 *
 * @author zhanghaijun
 * @since 2024-08-09
 */
public class DesensitizeSerializer extends JsonSerializer<String> implements ContextualSerializer {

    /**
     * 脱敏类型，默认为DEFAULT
     */
    private DesensitizeType desensitize;

    /**
     * 根据上下文信息创建自定义的序列化器，用于处理带有 @Desensitize 注解的属性。
     *
     * @param prov     序列化器提供者，用于获取其他序列化器
     * @param property 当前属性的信息，用于获取注解和属性类型
     * @return 自定义的序列化器实例
     */
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        Desensitize annotation = property.getAnnotation(Desensitize.class);
        // 判断属性类型是否为String，如果不是则不处理
        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass())) {
            this.desensitize = annotation.type();
            return this;
        }
        return prov.findValueSerializer(property.getType(), property);
    }

    /**
     * 序列化字符串时调用，根据脱敏类型对字符串进行相应的脱敏处理。
     *
     * @param value         待序列化的字符串
     * @param jsonGenerator JSON生成器，用于写入处理后的字符串
     * @param serializers   序列化器提供者，用于获取其他序列化器
     * @throws IOException 如果序列化过程中发生I/O错误
     */
    @Override
    public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (Objects.nonNull(desensitize) && Objects.nonNull(desensitize.getDesensitize())) {
            jsonGenerator.writeString(desensitize.getDesensitize().apply(value));
        } else {
            jsonGenerator.writeString(DesensitizeType.DEFAULT.getDesensitize().apply(value));
        }
    }
}
